<template>
  <div class="table-pro-layout">
    <el-container class="container-box">
      <div class="table-tools" v-if="showTools">
        <div class="tools-left">
          <slot name="tools"></slot>
        </div>
        <div class="tools-right">
          <el-button icon="Grid" @click="cloumnVisible = true"></el-button>
        </div>
      </div>
      <el-table ref="tablePro" class="table-pro" v-bind="$attrs" :data="data" header-row-class-name="table-head">
        <template v-for="item in columns" :key="item">
          <el-table-column
            v-if="item.type && ['selection', 'index', 'expand'].includes(item.type)"
            v-bind="item"
            :reserve-selection="item.type == 'selection'"
          >
            <template v-if="item.type == 'expand'" #default="scope">
              <component :is="item.render" v-bind="scope" v-if="item.render"> </component>
              <slot v-else :name="item.type" v-bind="scope"></slot>
            </template>
          </el-table-column>
          <ColumnPro v-else-if="item.show" :columns="item">
            <template v-for="slot in Object.keys($slots)" #[slot]="scope">
              <slot :name="slot" v-bind="scope"></slot>
            </template>
          </ColumnPro>
        </template>
      </el-table>
      <div class="table-pagination" v-if="showPage"></div>
    </el-container>
    <el-dialog v-model="cloumnVisible" title="栏目设置" width="500" :before-close="handleClose">
      <el-table :data="columns" style="width: 100%">
        <el-table-column prop="label" label="列名称" />
        <el-table-column prop="show" label="是否显示">
          <template #default="scope">
            <el-switch
              :disabled="scope.row.type === 'index' || scope.row.type === 'selection'"
              v-model="scope.row.show"
              inline-prompt
              active-text="是"
              inactive-text="否"
            />
          </template>
        </el-table-column>
        <el-table-column prop="fixed" label="固定">
          <template #default="scope">
            <el-select v-model="scope.row.fixed" placeholder="请选择">
              <el-option label="左固定" value="left" />
              <el-option label="右固定" value="right" />
              <el-option label="不固定" value="false" />
            </el-select>
          </template>
        </el-table-column>
      </el-table>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cloumnVisible = false">取消</el-button>
          <el-button type="primary" @click="cloumnVisible = false">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import type { TableProCloumn, TableProProps } from "@/typings";
import type { ElTable, TableInstance } from "element-plus";
import ColumnPro from "./ColumnPro.vue";
import { onUnmounted, ref, watch } from "vue";
defineOptions({
  name: "TablePro"
});
const columns = ref<TableProCloumn[]>([]);
const cloumnVisible = ref<boolean>(false);
const props = withDefaults(defineProps<TableProProps>(), {
  showTools: true,
  showPage: false
});
const tablePro = ref<TableInstance | undefined>();
const stopWatch = watch(
  () => props.columns,
  (newValue) => {
    newValue.forEach((item) => item.show ?? (item.show = true));
    columns.value = newValue;
  },
  {
    deep: true,
    immediate: true
  }
);
const handleClose = (done: () => void) => {
  done();
};

defineExpose({
  tablePro
});

onUnmounted(() => {
  stopWatch && stopWatch();
});
</script>

<style scoped lang="scss">
.table-pro-layout {
  width: 100%;
  height: 100%;
  .container-box {
    width: 100%;
    height: 100%;
    flex-direction: column;
    .table-tools {
      height: 42px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 4px;
      .tools-left {
        flex: 1;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: flex-start;
      }
      .tools-right {
        height: 100%;
        width: 80px;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
    .table-pro {
      height: 100%;
      width: 100%;
      overflow: auto;
    }
    :deep(.table-head) {
      .el-table__cell {
        // background-color: var(--el-aside-border-color);
        background-color: #e4e7ed;
      }
    }
    .table-pagination {
      height: 46px;
      display: flex;
      align-items: flex-end;
      justify-content: flex-end;
    }
  }
}
</style>

<!-- <template>
  <div class="table-pro-layout">
    <el-container class="container-box">
      <div class="table-tools" v-if="showTools">
        <div class="tools-left">
          <slot name="tools"></slot>
        </div>
        <div class="tools-right">
          <el-button icon="Grid" @click="cloumnVisible = true"></el-button>
        </div>
      </div>
      <el-table ref="tablePro" class="table-pro" v-bind="$attrs" :data="tableProData" header-row-class-name="table-head">
        <template v-for="item in columns" :key="item">
          <el-table-column
            v-if="item.type && ['selection', 'index', 'expand'].includes(item.type)"
            v-bind="item"
            :reserve-selection="item.type == 'selection'"
          >
            <template v-if="item.type == 'expand'" #default="scope">
              <component :is="item.render" v-bind="scope" v-if="item.render"> </component>
              <slot v-else :name="item.type" v-bind="scope"></slot>
            </template>
          </el-table-column>
          <ColumnPro v-else-if="item.show" :columns="item">
            <template v-for="slot in Object.keys($slots)" #[slot]="scope">
              <slot :name="slot" v-bind="scope"></slot>
            </template>
          </ColumnPro>
        </template>
      </el-table>
      <div class="table-pagination" v-if="showPage"></div>
    </el-container>
    <el-dialog v-model="cloumnVisible" :title="$t('table.columnSetting')" width="500" :before-close="handleClose">
      <el-table :data="columns" style="width: 100%">
        <el-table-column prop="label" :label="$t('table.columnName')" />
        <el-table-column prop="show" :label="$t('table.isShow')">
          <template #default="scope">
            <el-switch
              :disabled="scope.row.type === 'index' || scope.row.type === 'selection'"
              v-model="scope.row.show"
              inline-prompt
              :active-text="$t('table.yes')"
              :inactive-text="$t('table.no')"
            />
          </template>
        </el-table-column>
        <el-table-column prop="fixed" :label="$t('table.fixed')">
          <template #default="scope">
            <el-select v-model="scope.row.fixed" :placeholder="$t('table.select')">
              <el-option :label="$t('table.leftFixed')" value="left" />
              <el-option :label="$t('table.rightFixed')" value="right" />
              <el-option :label="$t('table.noFixed')" value="false" />
            </el-select>
          </template>
        </el-table-column>
      </el-table>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cloumnVisible = false">{{ $t("table.cancel") }}</el-button>
          <el-button type="primary" @click="cloumnVisible = false"> {{ $t("table.ok") }} </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import type { TableProCloumn, TableProProps } from "@/typings";
import type { ElTable, TableInstance } from "element-plus";
import ColumnPro from "./ColumnPro.vue";
import { onUnmounted, ref, watch, type VNode } from "vue";
import { isUndefinedOrNull } from "@/utils";
defineOptions({
  name: "TablePro"
});
const columns = ref<TableProCloumn[]>([]);
const tableProData = ref<any[]>([]);
const cloumnVisible = ref<boolean>(false);
const props = withDefaults(defineProps<TableProProps>(), {
  showTools: true,
  showPage: false
});
const tablePro = ref<TableInstance | undefined>();
const stopWatch = watch(
  () => props.columns,
  (newValue) => {
    newValue.forEach((item) => item.show ?? (item.show = true));
    columns.value = newValue;
  },
  {
    deep: true,
    immediate: true
  }
);

const stopWatchData = watch(
  () => props.data,
  (newValue) => {
    tableProData.value = newValue;
    columns.value.forEach((item) => {
      if (item.filter && item.filter === true && item.prop) {
        item.filters = getFilters(item.prop, item);
        item.filterMethod = filterMethod;
      }
    });
  },
  {
    deep: true,
    immediate: true
  }
);

function isFunction(fn: any): boolean {
  if (!fn) return false;
  return typeof fn === "function";
}

function getFilters(prop: string, column: TableProCloumn): { text: string; value: string }[] {
  const resultStack: { text: string; value: string }[] = [];
  for (const item in tableProData.value) {
    const objItem = tableProData.value[item][prop];
    if (!isUndefinedOrNull(objItem)) {
      const obj: { text: string; value: string } = {
        // 获取当前列的render函数拿到内容
        text: isFunction(column.render)
          ? ((
              (
                column.render!({
                  row: tableProData.value[item],
                  $index: 0,
                  column: column
                }) as VNode
              ).children as Array<string>
            )[0] as string)
          : objItem,
        value: objItem
      };
      if (!resultStack.find((item) => item.value === obj.value)) {
        resultStack.push(obj);
      }
    }
  }
  return resultStack;
}

function filterMethod(value: string, row: any, column: TableProCloumn) {
  const property = column["property"] as string;
  return row[property] === value;
}

const handleClose = (done: () => void) => {
  done();
};

defineExpose({
  tablePro
});

onUnmounted(() => {
  stopWatch && stopWatch();
  stopWatchData && stopWatchData();
});
</script>

<style scoped lang="scss">
.table-pro-layout {
  width: 100%;
  height: 100%;
  .container-box {
    width: 100%;
    height: 100%;
    flex-direction: column;
    .table-tools {
      height: 42px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 4px;
      .tools-left {
        flex: 1;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: flex-start;
      }
      .tools-right {
        height: 100%;
        width: 80px;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
    .table-pro {
      height: 100%;
      width: 100%;
      overflow: auto;
    }
    :deep(.table-head) {
      .el-table__cell {
        background-color: var(--el-aside-border-color);
      }
    }
    .table-pagination {
      height: 46px;
      display: flex;
      align-items: flex-end;
      justify-content: flex-end;
    }
  }
}
</style> -->
